#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>

const bool INTERNET = false;

// WiFi
const char *ssid = "熟读深思子自知"; // Enter your WiFi name
const char *password = "kongzi,2020";  // Enter WiFi password

// MQTT Broker
const char *mqtt_broker = "31141TC4QV.iotcloud.tencentdevices.com";
const char *topic = "$thing/up/property/31141TC4QV/esp8266"; // 上传到腾讯云的信息
const char *downtopic = "$thing/down/property/31141TC4QV/esp8266"; // 腾讯云下发的指令
const char *mqtt_username = "31141TC4QVesp8266;12010126;TO3O0;4804538844"; // 用户名和密码有时效性
const char *mqtt_password = "be4558a6447f6f25e5ec5770984dd37759502974eb9b141d6bec49a649a2e1e1;hmacsha256";
const int mqtt_port = 1883;
const String client_id = "31141TC4QVesp8266"; // 标识当前设备的客户端编号

// 继电器记下的上次时间
unsigned long last_time; 

// 站立时间，默认40分钟=2400000
unsigned long sitdown=2400000; 

int controlPin = 0;   //定义变量controlPin为引脚D0 继电器引脚控制。下载模式：外部拉低；运行模式：悬空或者外部拉高。
int ledPin = 2; // GPIO2 of ESP8266-01S 板载的LED灯控制,方便当前工作状态识别
bool standup=false; // 区分站立状态 ，初始化应该是坐着
// 工作是否开启
bool turn_on = true;

WiFiClient espClient;
PubSubClient client(espClient);


void setup() {
    // 板子通电后要启动，稍微等待一下让板子点亮
    delay(10);
    last_time= millis();
    Serial.begin(115200);
    pinMode(controlPin, OUTPUT);     //将变量controlPin（引脚D0）通过pinMode函数设置为输出模式
    pinMode(ledPin, OUTPUT);
    digitalWrite(controlPin, HIGH);
    digitalWrite(ledPin, HIGH);

    if (INTERNET){
      // connecting to a WiFi network
      WiFi.begin(ssid, password);
      // TODO 30次就直接结束。离线也要正常使用
      int count = 30;
      while (WiFi.status() != WL_CONNECTED && count > 0) {
          count = count-1;
          delay(500);
          Serial.println("Connecting to WiFi..");
      }
      Serial.print("Connected to the WiFi network.IP address: ");
      Serial.println(WiFi.localIP());
      
      //connecting to a mqtt broker
      client.setServer(mqtt_broker, mqtt_port);
      client.setCallback(callback);

      reconnect();
    }
}

// MQTT重连
void reconnect() {
    // TODO 5次失败，直接放弃。离线也要正常使用
    int count = 5;
    while (!client.connected() && count > 0) {
        count=count-1;
        Serial.printf("The client %s connects to the public mqtt broker\n", client_id.c_str());
        if (client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {
            Serial.println("Public emqx mqtt broker connected");
            // publish and subscribe
            //client.publish(topic, client_id.c_str()); // String的c_str()方法将一个字符串转换为字符数组
            client.subscribe(downtopic);
        } else {
            Serial.print("failed with state ");
            Serial.println(client.state());
            delay(1500);
        }
    }
}

void callback(char *topic, byte *payload, unsigned int length) {
    Serial.print("Message arrived in topic: ");
    Serial.println(topic);
    Serial.println("Message:");
    String msg="";
    for (int i = 0; i < length; i++) {
        //Serial.print((char) payload[i]);
          msg += (char)payload[i];
    }
    Serial.println(msg);

    DynamicJsonDocument doc(1024);
    deserializeJson(doc, msg);

    // 这个没办法递归到子的对象中
     if(doc.containsKey("switch")){
       Serial.println("contains switch1");
     }

    if(doc.containsKey("params")){
       Serial.println("contains params");
    }
    
    const char* paramsObject = doc["params"];
    Serial.println(paramsObject);

    JsonVariant switch_exsit = doc["params"]["switch"];    
    long switch1 = 3; // 给个默认值3
    if(!switch_exsit.isNull()){
      Serial.println("switch_exsit!");
      switch1 = doc["params"]["switch"];
      Serial.println(switch1);
    }

    long sitdown_time = doc["params"]["sitdown"];
    if(sitdown_time > 0){
      sitdown = sitdown_time * 1000 * 60;
    }

    Serial.println(sitdown);
    char* status="turn on";
    if(msg=="ok"||msg=="yes" || switch1==1){
      turn_on=true;
//      digitalWrite(ledPin, LOW); // 灯亮
      Serial.println("turn on !");      
    }else if(msg=="no"|| switch1==0){
      turn_on=false;
      status="turn off";
//      digitalWrite(ledPin, HIGH); // 灯灭
      Serial.println("turn off !");
    }
    Serial.println(msg);
    Serial.println(switch1);
    // TODO 这里需要返回信息，以确认接收到了指令
    //client.publish(topic, String("lege copy that").c_str());
    Serial.println("-----------------------");
}

// 继电器的开关触发
void jidianqi(int pin){
      digitalWrite(pin, LOW);  
      delay(800);
      digitalWrite(pin, HIGH); 
}


void loop() {

    if (INTERNET){
        // MQTT消息连接
        if (!client.connected()) {
          reconnect();
        }
        client.loop();
    }

    long current_time=millis();
    long gap =  current_time - last_time;
    if(turn_on){
       if(standup){
        
        // 现在是站立状态，应该是站6分钟后就坐下去
          if(gap>=360000){
              standup=false;
              last_time=current_time;
              // 执行一次
              jidianqi(ledPin);
              Serial.println("sit down--");
          } 
      }else{
          // 坐着的时候，判断时间是否超过30分钟
           if(gap>=1800000){
              standup=true;
              last_time=current_time;
              // 执行一次
              jidianqi(controlPin);
              Serial.println("stand up--");
          } 
      }
    }else{
      last_time=current_time;
    }
}
